<template>
  <van-form @submit="loginSubmit" class="login">
    <!----------------- 1. 头部图片 ---------------------->
    <van-image
      width="auto"
      :src="loginState.logoImage"
    />
    <van-cell-group inset>
      <!---------------- 2. 用户名 ----------------------->
      <van-field
        v-model="loginState.username"
        name="用户名"
        label="用户名"
        placeholder="用户名"
      />
      <!----------------- 3. 密码 ------------------------>
      <van-field
        v-if="loginState.isPassword"
        v-model="loginState.password"
        type="password"
        name="密码"
        label="密码"
        placeholder="密码"
      />
      <!----------------- 4. 短信验证码 ------------------->
      <van-field
        v-else
        v-model="loginState.captcha"
        center
        clearable
        label="短信验证码"
        placeholder="请输入短信验证码"
      >
        <template #button>
          <!-- 当倒计时开始时禁用按钮，倒计时结束禁用按钮失效 -->
          <van-button size="small" type="primary" @click="sendCaptcha" :disabled="loginState.isSend">{{ loginState.captchaText }}</van-button>
        </template>
      </van-field>
    </van-cell-group>
    <!---------------- 5. 提交和登录模式切换 ----------------->
    <div style="margin: 16px;">
      <van-button round block type="primary" native-type="submit">
        登录
      </van-button>
      <!-- 切换登录模式按钮 -->
      <span
        class="changeLogin"
        @click="changeMode"
        v-text="loginState.changeText"
      />
    </div>
  </van-form>
</template>
<script setup>
import { reactive, computed } from 'vue'
import { showToast } from 'vant'
// 提供倒计时管理能力的组合式 API
import { useCountDown } from '@vant/use'
import { getLogoImage } from '@/api/home'
import { getVerifyCode, getCaptcha, passwordLogin, captchaLogin } from '@/api/user'
import { useRouter, useRoute } from 'vue-router'
// 引入根 store 方法
import useStore from '@/store/index'
// 执行方法 useStore，通过解构的方式获取到 userStore 用户管理实例
const { userStore } = useStore()
// 操作路由实例
const router = useRouter()
// 获取路由信息的实例
const route = useRoute()
/* --------------------------- 数据处理 ------------------------ */
// 1. 声明响应式对象，存储登录组件所需的数据
// 存储倒计时实例，这个变量必须单独创建，因为当做一个属性创建在 loginState 中时，通过 .seconds 获取剩余秒数时会报错
let current = null
const loginState = reactive({
  loginMode: 'password', // 登录模式，值为 'password' 是密码模式，值为 'captcha' 是验证码模式
  isPassword: computed(() => loginState.loginMode === 'password'), // 是否密码模式
  username: '', // 用户名
  password: '', // 密码
  captcha: '', // 短信验证码
  // 切换登录模式按钮的文字替换，密码模式时文字为 '快速登录'，反之文字为 '密码登录'
  changeText: computed(() => loginState.isPassword ? '快速登录' : '密码登录'),
  isSend: false, // 验证码请求发送状态，默认为 false，没有发送
  // 控制发送验证码按钮显示的文字，发送验证码成功后，显示倒计时毫秒
  captchaText: computed(() => loginState.isSend ? current.value.seconds + 's' : '发送验证码'),
  logoImage: '' // 存储 Logo 图片地址
})

// 2. 切换登录模式函数
const changeMode = () => {
  // 如果当前是密码模式，点击按钮后切换为验证码模式，反之切回密码模式
  loginState.loginMode = loginState.isPassword ? 'captcha' : 'password'
  // 模式切换后，要清空之前填写的密码或者验证码
  loginState.password = ''
  loginState.captcha = ''
}

/* --------------------------- 验证码处理 ------------------------ */
// 1. 创建倒计时实例，实例不可以在 async 函数中创建，否则会有警告
const countDown = useCountDown({
  // 倒计时时长，单位毫秒，倒计时默认每秒渲染一次；倒计时实际为 60 s，这里是演示使用
  time: 10 * 1000,
  // 倒计时结束时触发的回调函数
  onFinish: () => {
    loginState.isSend = false
  }
})
// 2. 发送验证码请求
const sendCaptcha = async () => {
  // 1.1 手机号规则校验
  if (!/^1\d{10}$/.test(loginState.username)) {
    return showToast('手机号格式不正确')
  }
  // 1.2 发送校验请求，获取到用户校验码
  const { data: verifyCode } = await getVerifyCode()
  if (verifyCode.status !== 200) { return showToast('校验失败') }
  // 1.3 发送短信验证码请求，获取到短信验证码
  const { data } = await getCaptcha({
    key: verifyCode.data.key, // 校验码
    phone: loginState.username, // 手机号
    type: 'login' // 类型为登录
  })
  console.log(data)
  if (data.status !== 200) { return showToast('短信验证码获取失败') }
  // 1.4 验证码请求发送成功，开始倒计时
  countDown.start()
  // 将验证码发送状态改为 true
  loginState.isSend = true
  // 记录当前倒计时实例
  current = countDown.current
}

/* --------------------------- 登录处理 ------------------------ */
// 4. 表单提交触发的函数
const loginSubmit = async () => {
  // 用户名检测
  const username = loginState.username.trim()
  if (username === '' && !/^1\d{10}$/.test(username)) { return showToast('用户名格式不对') }
  // 使用变量保存，为了统一处理不同模式下的响应结果
  let data = ''
  if (loginState.isPassword) {
    // 1. 密码模式，密码不能为空
    const password = loginState.password.trim()
    if (password === '') { return showToast('密码不能为空') }
    // 使用 () 形式，就可以把解构的数据提取出来，赋值给上面定义的变量 data
    ({ data } = await passwordLogin({
      account: username,
      password
    }))
  } else {
    // 2. 验证码模式，验证码不能为空
    const captcha = loginState.captcha.trim()
    if (captcha === '') { return showToast('验证码不能为空') }
    ({ data } = await captchaLogin({
      phone: username,
      captcha
    }))
  }
  // 接收响应数据失败
  if (data.status !== 200) { return showToast('账号或者密码错误') }
  // 接收响应数据成功
  // 执行用户状态管理器中的方法 setUser，让 token 作为参数传递，记录用户的登录状态
  userStore.setUser(data.data.token)
  // 登录成功后，跳转到用户本来就要去的页面；如果用户是直接输入 /login，那么登录后跳转到用户页面
  // 空值合并符 ??，前面没有的时候，访问后面的值
  router.push(route.query.redirect ?? '/user')
}

/* --------------------------- Logo 图片处理 ------------------------ */
// 5. 发送获取 Logo 图片请求
const initLogoImage = async () => {
  const { data } = await getLogoImage()
  if (data.status !== 200) return
  loginState.logoImage = data.data.logo_url
}
initLogoImage()
</script>
<style lang='scss' scoped>
.login {
  text-align: center;
  padding-top: 100px;
  .van-image {
    margin-bottom: 10px;
  }
  .changeLogin {
    font-size: 14px;
    color: #999;
  }
  // 验证码按钮，保证倒计时宽度一致
  :deep(.van-field__button) {
    .van-button {
      width: 80px;
    }
  }
}
</style>
